package control;

import debug.Console;
import types.Complemento;
import types.ComplementoAux;
import types.Sentence;
import types.SubstantivoSimple;
import types.SujetoSimple;

public class Semantic {
	private Sentence sentence;
	
	public Semantic(Sentence _sen) {
		sentence = _sen;
	}
	
	public boolean checkTypes() throws Exception {
		if (sentence.isFrase_simple()) {
			// No check for Frase Simple
			return true;
		}
		
		TypeFilter sujeitoType = getSujetoSimpleType(sentence.getSujeito().getLeft());
		Console.addInfoLine("Check sujeito left : " + sujeitoType.toString());
		if (sentence.getSujeito().isConf()) {
			TypeFilter rightType = getSujetoSimpleType(sentence.getSujeito().getRight());
			Console.addInfoLine("Check sujeito right : " + rightType.toString());
			sujeitoType = mergeConjType(sujeitoType, rightType);
			Console.addInfoLine("Merged : " + sujeitoType.toString());
		}
		
		Console.addInfoLine("Verbo type : " + sentence.getVerb().getTypeFilterAccord());
		if (!sentence.getVerb().checkTypeFilter(sujeitoType)) {
			throw new Exception("Subject type is " + sujeitoType + ", and verb type is " + sentence.getVerb().getTypeFilterAccord());
		} else {
			Console.addInfoLine("Verbo type : OK");
		}
		
		if (checkCompl(sentence.getCompl(), sujeitoType)) {
			Console.addInfoLine("Check Complemento OK");
		}
		
		return true;
	}
	
	private boolean checkCompl(Complemento compl, TypeFilter sujeito) throws Exception {
		TypeFilter subtype = checkSubtanvitoSimple(compl.getSub());
		
		if (!(subtype.getGenre().equals(sujeito.getGenre())
				&& subtype.getPlural().equals(sujeito.getPlural()))) {
			throw new Exception("Complemento type " + subtype + " don't match with sujeito : " + sujeito);
		} else {
			Console.addInfoLine("  Complemento type " + subtype + " match with sujeito : " + sujeito);
		}
		
		for (int i = 0; i < compl.getComplaux().size(); i++) {
			if (!checkComplAux(compl.getComplaux().get(i))) {
				return false;
			}
		}
		return true;
	}
	
	private boolean checkComplAux(ComplementoAux compl) throws Exception {
		TypeFilter type = null;
		
		if (checkSubtanvitoSimple(compl.getSub()) != null) {
			return true;
		}
		return false;
	}
	
	private TypeFilter checkSubtanvitoSimple(SubstantivoSimple ss) throws Exception {
		TypeFilter ret = null;
		
		String retstr = " Checking : " + ss + " : ";
		
		if (ss.getArt() != null) {
			ret = ss.getArt().getTypeFilterAccord();
		}
		
		if (ss.getSub() != null) {
			if (ret != null) {
				if (!ss.getSub().checkTypeFilter(ret)) {
					throw new Exception("The noun " + ss.getSub().getWord() + " is " + ss.getSub().getTypeFilterAccord() + " and don't match with article " + ret.toString());
				}
			} else {
				ret = ss.getSub().getTypeFilterAccord();
			}
		}
		
		if (ss.getAdj() != null) {
			if (ret != null) {
				if (!ss.getAdj().checkTypeFilter(ret)) {
					throw new Exception("The adjective " + ss.getAdj().getWord() + " is " + ss.getAdj().getTypeFilterAccord() + " and don't match with " + ret.toString());
				}
			} else {
				ret = ss.getAdj().getTypeFilterAccord();
			}
		}
		Console.addInfoLine(retstr + "OK : " + ret);
		return ret;
	}
	
	private TypeFilter mergeConjType(TypeFilter left, TypeFilter right) {
		TypeFilter ret = new TypeFilter();
		 
		if ((!left.getGenre().equals(TypeFilter.NONE) && !right.getGenre().equals(TypeFilter.NONE))) {
			if (left.getGenre().equals(Type.FEMININO)
				&& right.getGenre().equals(Type.FEMININO)) {
				ret.setGenre(Type.FEMININO);
			} else {
				if (!(left.getGenre().equals(TypeFilter.NONE) && right.getGenre().equals(TypeFilter.NONE))) {
					ret.setGenre(Type.MASCULINO);
				}
			}
		}
		
		if (left.getConjug_pers().equals(Type.PES_1)
				|| right.getConjug_pers().equals(Type.PES_1)) {
			ret.setConjug_pers(Type.PES_1);
		} else if (left.getConjug_pers().equals(Type.PES_2)
				|| right.getConjug_pers().equals(Type.PES_2)) {
			ret.setConjug_pers(Type.PES_2);
		} else {
			ret.setConjug_pers(Type.PES_3);
		}
		
		
		ret.setPlural(TypeFilter.PLURAL);
		
		return ret;
	}
	
	public TypeFilter getSujetoSimpleType(SujetoSimple ss) throws Exception {
		TypeFilter ret = null;
		
		if (ss.getArt() != null) {
			ret = ss.getArt().getTypeFilterAccord();
		}
		
		if (ss.getSub() != null) {
			if (ret != null) {
				if (!ss.getSub().checkTypeFilter(ret)) {
					throw new Exception("The noun " + ss.getSub().getWord() + " is " + ss.getSub().getTypeFilterAccord() + " and don't match with article " + ret.toString());
				}
			} else {
				ret = ss.getSub().getTypeFilterAccord();
			}
		}
		
		if (ss.getAdj() != null) {
			if (ret != null) {
				if (!ss.getAdj().checkTypeFilter(ret)) {
					throw new Exception("The adjective " + ss.getAdj().getWord() + " is " + ss.getAdj().getTypeFilterAccord() + " and don't match with " + ret.toString());
				}
			} else {
				ret = ss.getAdj().getTypeFilterAccord();
			}
		}
		
		if (ss.getPronom() != null) {
			ret = ss.getPronom().getTypeFilterAccord();
		} else {
			if (ret.getConjug_pers().equals(TypeFilter.NONE)) {
				ret.setConjug_pers(Type.PES_3);
			}
		}
		
		return ret;
	}
}
